package com.rois.librois.libRoISComponentServer;

import java.util.logging.Logger;


import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
import org.omg.PortableServer.POA;

import com.rois.librois.RoIS.ComponentBase;
import com.rois.librois.RoIS.ComponentBaseHelper;
import com.rois.librois.libRoISCommon.ServerThread;

/**
 * Implementation of common interface for CORBA server operation.
 *
 * @author Miki Sato <miki.sato.1225@gmail.com>
 *
 *    The MIT licence
 *
 *    Copyright (C) 2011
 *      ATR Intelligent Robotics and Communication Laboratories, Japan
 *
 *    Permission is hereby granted, free of charge, to any person obtaining a copy
 *    of this software and associated documentation files (the "Software"), to deal
 *    in the Software without restriction, including without limitation the rights
 *    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 *    of the Software, and to permit persons to whom the Software is furnished to do so,
 *    subject to the following conditions:
 *
 *    The above copyright notice and this permission notice shall be included in all
 *    copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 *    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 *    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

public class ServerOperationImpl implements com.rois.librois.libRoISCommon.ServerOperation
{
	private ORB m_orb;
	private POA m_poa_ref;
	private ServerImpl m_server_impl;
	public void setServerImpl(ServerImpl server_impl_val){
		m_server_impl = server_impl_val;
	}
	String m_servername;
	ServerThread m_thread;

	@Override
	public boolean initialize(
			String nameserver
	)
	{
		boolean bRes = false;
		try {
			// Initialize ORB
			String argv[] = new String[2];
			argv[0] = "-ORBInitRef";
			String strNameService1 = "NameService=corbaloc:iiop:";
			String strNameService2 = "/NameService";
			String strNameService = strNameService1 + nameserver + strNameService2;
			argv[1] = strNameService;
			m_orb = org.omg.CORBA.ORB.init(argv, null);

			// Obtain a reference to the root POA
			m_poa_ref = (POA)m_orb.resolve_initial_references("RootPOA");
			m_poa_ref.the_POAManager().activate();
		} catch (Exception e) {
			Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info("failed to initialize ORB.");
			return bRes;
		}
		bRes = true;
		return bRes;
	}

	@Override
	public boolean register(
		String servername
	)
	{
		boolean bRes = false;
		m_servername = servername;
		try {
			// Obtain the object for this Server
			org.omg.CORBA.Object ref;
			ref = m_poa_ref.servant_to_reference(m_server_impl);
			ComponentBase comp_ref;		// ***Component Interface***
			comp_ref = ComponentBaseHelper.narrow(ref);

			// Obtain the NameService
			org.omg.CORBA.Object obj_ref;
			obj_ref = this.m_orb.resolve_initial_references("NameService");

			// Narrow the reference of the NameService
			NamingContextExt nc_ref;
			nc_ref = NamingContextExtHelper.narrow(obj_ref);

			// Register the server name to the NameService
			NameComponent path[];
			path = nc_ref.to_name(servername);
			try{
				nc_ref.bind(path, comp_ref);
			}
			catch(AlreadyBound e)
			{
				nc_ref.rebind(path, comp_ref);
			}
		} catch (Exception e) {
			Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info("failed to register Server.");
			return bRes;
		}
		bRes = true;
		return bRes;
	}

	@Override
	public boolean start()
	{
		boolean bRes = false;
		if(m_orb!=null)
		{
			// Start the server thread
			m_thread = new ServerThread();
			m_thread.setORB(m_orb);
			m_thread.start();
		}
		else
		{
			Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info("failed to start Server.");
		}

		bRes = true;
		return bRes;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void stop()
	{
		if(m_orb!=null)
		{
			try{
				// Obtain the Name Service
				org.omg.CORBA.Object obj_ref;
				obj_ref = this.m_orb.resolve_initial_references("NameService");

				// Narrow the reference of NameService
				NamingContextExt nc_ref;
				nc_ref = NamingContextExtHelper.narrow(obj_ref);

				// Unregister the Server Name to from NameService
				NameComponent path[];
				path = nc_ref.to_name(m_servername);
				nc_ref.unbind(path);
			} catch (Exception e) {
				Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info("failed to unregist Server.");
			}
			m_orb = null;

			// Stop the server thread
			if(m_thread!=null)
			{
				if(m_thread.isAlive())
				{
					m_thread.stop();
					m_thread = null;
				}
			}
		}
	}
}
